package com.sticktogether.services;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;

import com.sticktogether.MapViewActivity;
import com.sticktogether.R;
import com.sticktogether.photoreceiver.PhotoDatabase;
import com.sticktogether.server.ServerCommunication;

public class UploadService extends Service  {

	private static final String serverurl = "http://www.wirhassenalledenjul.de/fotos/android_upload.php";
	protected static final int ID = 2;
	private boolean startedInForeground = false;
	private NotificationCompat.Builder mBuilder;
	private NotificationManager mNotifyManager;
	private Notification notification;
	private int overhead = 0;
	private int alreadyUploaded = 0;
	private int overall = 0;

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		
		
		uploadPictures();
		
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		int size;
		PhotoDatabase photoDB = ServerCommunication.getPhotoDb(this);
		synchronized (photoDB) {
			SQLiteDatabase db = photoDB.getReadableDatabase();
			Cursor cursor = db.query("photos", null, null, null, null, null, null);
			size = cursor.getCount();
			cursor.close();
			db.close();
		}
		overall = size + alreadyUploaded;
		
		return super.onStartCommand(intent, flags, startId);
	}
	
	private void uploadPictures() {

		new Thread(
		    new Runnable() {
				public void run() {
					
					thread:
						// just in case that we loos connection and want to break thread;
						for(int j=1; j==1; j++) {
							// Wait 100ms untill overall number from onStart function is loaded.
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							
							// do unitll there are no more photos or Internet connection is lost
							while(true) {
								
								PhotoDatabase photoDB = ServerCommunication.getPhotoDb(UploadService.this);
								// First of all get all album ids for unchecked photos
								// If the photos have not been taken during an event, they will be removed.
								while(true) {
									synchronized (photoDB) {
										
										// get number of photos that have not been checked jet
										// checked means: taken during event? if so which event?
										SQLiteDatabase db = photoDB.getReadableDatabase();
										Cursor cursor = db.query("photos", null, "album_id = 0", null, null, null, null);
										int size = cursor.getCount();
										
										// no unchecked photos, continue...
										if(size==0) {
											cursor.close();
											db.close();
											break;
										}
										// ok we have unchecked photos...
										else {
										    cursor.moveToFirst();
										    // check all of them
										    for(int i=0; i<size; i++) {
										    	// call getAlbumId for every photo with album_id == 0
										    	String time = cursor.getString(cursor.getColumnIndex("time"));
										    	ServerCommunication.getAlbumId(time, UploadService.this);
										    }
										    cursor.close();
											db.close();
										}
									}
									// wait a second and hope that all album ids have been loaded afterwards.
									// if not we run through the loop once again.
									try {
										Thread.sleep(1000);
									} catch (InterruptedException e) {
										e.printStackTrace();
									}
								}
								
								// all photos in the database have an album id now and need to be uploaded
								// get all entries from the database
								SQLiteDatabase db = photoDB.getReadableDatabase();
								Cursor cursor = db.query("photos", null, null, null, null, null, null);
								int size = cursor.getCount();
								// if we do not have any entries, break
								if(size==0) break;
								// otherwise, if we run through the loop for the first time:
								// start the service in foreground (includes creating a notification)
								else if(!startedInForeground) {
									startInForeground();
									startedInForeground = true;
								}
								
								// upload every photo that has an entry in the database
							    cursor.moveToFirst();
							    for(int i=0; i<size; i++) {
								    String imagePath = cursor.getString(cursor.getColumnIndex("path"));
								    String albumid = cursor.getString(cursor.getColumnIndex("album_id"));
								    String istopicid = cursor.getString(cursor.getColumnIndex("istopicid"));
								    
					                // update Notification
				                    mBuilder.setProgress(overall, i+overhead, false);
				                    mBuilder.setContentTitle(String.format(getString(R.string.image_upload_number),i+1+overhead,overall));
				                    notification = mBuilder.build();
				                    startForeground(ID, notification);
				                    
				                    // upload picture
				                    java.io.File file = new java.io.File(imagePath);
				                    if(file.exists()) {
				                    	boolean uploadScucessfull = uploadPicture(imagePath, albumid, istopicid);
				                    	// internet connection has been lost.
				                    	// Break and write a notification.
				                    	if(!uploadScucessfull) {
					                    	String notificationText = "";
								            String notificationTitle = getString(R.string.image_album_upload_interrupted);
								            finishService(notificationTitle, notificationText);
								            break thread;
				                    	}
				                    }
				                    
				                    // Upload has been successful. Remove corresponding entry from the database
				                    synchronized (photoDB) {
					                    SQLiteDatabase db2 = photoDB.getWritableDatabase();
					                    db2.delete("photos", "path = '" + imagePath + "'", null);
					                    alreadyUploaded++;
					                    db2.close();
				                    }
				                    cursor.moveToNext();
					            }
							    
							    // we need this to still show a correct notification
							    // if the number of pictures in the database increases during an upload process
							    // and we run through the outer while loop more than once.
							    overhead += size;
					            
							    cursor.close();
							    db.close();
							}
				            
							// If pictures have been uploaded, we have started the service in foreground.
							// Then we want to show a notification for the successful upload.
							if(startedInForeground) {
					            String notificationText = getString(R.string.image_album_notification_click);
					            String notificationTitle = getString(R.string.image_uploaded);
					            finishService(notificationTitle, notificationText);
							}
						}
		        }


				private boolean uploadPicture(String imagePath, String albumid, String istopicid) {
					HttpClient httpclient = new DefaultHttpClient();
					HttpPost httppost = new HttpPost(serverurl);
					
					MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
					File file = new File(imagePath);
					
					entity.addPart("userpicture", new FileBody(file));
					try {
						
						if(istopicid == null) {
							entity.addPart("album", new StringBody(albumid));
						}
						else {
							entity.addPart("topic", new StringBody(albumid));
						}
						entity.addPart("id", new StringBody(ServerCommunication.getUserId()));
						entity.addPart("sid", new StringBody(ServerCommunication.getPassword()));
					} catch (UnsupportedEncodingException e1) {
						e1.printStackTrace();
					}
				    
					httppost.setEntity(entity);
					try {
					    /* when you uncomment this, comment httpclient.execute(httppost);
					    
					    ResponseHandler<String> responsehandler = new BasicResponseHandler();
					    String responseBody = httpclient.execute(httppost, responsehandler);

					    if (responseBody != null && responseBody.length() > 0) {
					        Log.w("UPLOAD", "Response image upload " + responseBody);
					    }*/
						
						httpclient.execute(httppost);
						
					} catch (ClientProtocolException e) {
						return false;
					} catch (IOException e) {
			            return false;
					}
					return true;
					
				}


				private void finishService(String title, String text) {
					// updates the notification
		            String url = "http://www.wirhassenalledenjul.de/fotos/index.php?cat=2";
		            Intent resultIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
		            // The stack builder object will contain an artificial back stack for the
		            // started Activity.
		            // This ensures that navigating backward from the Activity leads out of
		            // your application to the Home screen.
		            TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());

		            // Adds the Intent that starts the Activity to the top of the stack
		            stackBuilder.addNextIntent(resultIntent);
		            PendingIntent resultPendingIntent =
		                    stackBuilder.getPendingIntent(
		                        0,
		                        PendingIntent.FLAG_UPDATE_CURRENT
		                    );
		            
		            mBuilder.setContentText(text)
		            		.setContentTitle(title)
		            		// Removes the progress bar
		                    .setProgress(0,0,false)
		            		.setAutoCancel(true)
		            		.setContentIntent(resultPendingIntent);
                    
                    stopForeground(true);
                    mNotifyManager.notify(ID,mBuilder.build());
                    
                    // stop service
                    stopSelf();
                    
                    
				}
		    }
		).start();
		
	}
	
	private void startInForeground() {
		mNotifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		mBuilder = new NotificationCompat.Builder(this);
		mBuilder.setContentTitle("Upload")
		    .setContentText(getString(R.string.image_uploading))
		    .setSmallIcon(R.drawable.stub_image);
		
        // Creates an explicit intent for an Activity in your app
        Intent notificationIntent = new Intent(this, MapViewActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);


        // Adds the Intent that starts the Activity to the top of the stack
        mBuilder.setContentIntent(pendingIntent);
		
        notification = mBuilder.build();
		startForeground(ID, notification);
	}
	
	/*private void listDatabase() {
		SQLiteDatabase db2 = photos.getReadableDatabase();
		Cursor cursor = db2.query("photos", null, null, null, null, null, null);
		int length = cursor.getCount();
		String[] pathNames = new String[length];
	    cursor.moveToFirst();
	    for(int i=0; i<length; i++) {
	      pathNames[i] = cursor.getString(cursor.getColumnIndex("path"));
	      Log.d("TAG2", "file Path" +  pathNames[i] + " (" + cursor.getString(cursor.getColumnIndex("album_id")) + ", " + cursor.getString(cursor.getColumnIndex("time")) + ")");
	      cursor.moveToNext();
	    }
	    cursor.close();
		db2.close();
	}*/

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

}
